
`include "common_header.verilog"

//  *************************************************************************
//  File : ff_sreset
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited.
//  Copyright (c) 2008 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Daniel Koehler
//  info@morethanip.com
//  *************************************************************************
//  Description : FIFO sync reset controller for both clock domains.
//  Version     : $Id: ff_sreset.v,v 1.2 2015/12/14 11:48:34 dk Exp $
//  *************************************************************************
module ff_sreset (
   
   reset_lclk,
   lclk,
   lsreset_in,
   lsreset_done,
   lsreset_out,
   reset_oclk,
   oclk,
   osreset_out);

input   reset_lclk;     //  Active High Reset for lclk domain
input   lclk;           //  local clock             
input   lsreset_in;     //  reset pulse (edge detected) in lclk domain
output   lsreset_done;  //  reset cycle completed (pulse)
output   lsreset_out;   //  active high, sync to lclk
input   reset_oclk; 
input   oclk; 
output   osreset_out; 

//  local clock where reset occurs
// -------------------------------

reg     lsreset_done; 
wire    lsreset_out; 

//  other clock domain
//  ------------------
wire    osreset_out; 
reg     lr_latch; //  latched sync reset in
wire    lrst_reg2; 

//  oclk
wire    orst_reg2; 
reg     orst_reg3; 
reg     orst_reg4; 

//  local clock
//  -----------

always @(posedge reset_lclk or posedge lclk)
   begin : pl
   if (reset_lclk == 1'b 1)
      begin
      lr_latch <= 1'b 0;	
      lsreset_done <= 1'b 0;	
      end
   else
      begin

        //  latch reset request

      if (lsreset_in == 1'b 1)
         begin
         lr_latch <= 1'b 1;	
         end
      else if (lrst_reg2 == 1'b 1 )
         begin
         lr_latch <= 1'b 0;	
         end

        //  indicate end of cycle (pulse)

      if (lr_latch == 1'b 1 & lrst_reg2 == 1'b 1)
         begin
         lsreset_done <= 1'b 1;	
         end
      else
         begin
         lsreset_done <= 1'b 0;	
         end

      end
   end

//  get back indication from other clock domain
//  ------------------------------------------

mtip_xsync #(1) U_SYLCK (
        .data_in(orst_reg4),      //  from write clock domain
        .reset  (reset_lclk),
        .clk    (lclk),
        .data_s (lrst_reg2));


//  transfer reset indication into other clock
//  ------------------------------------------
mtip_xsync #(1) U_SYOCK (
        .data_in(lr_latch),      //  from write clock domain
        .reset  (reset_oclk),
        .clk    (oclk),
        .data_s (orst_reg2));


always @(posedge reset_oclk or posedge oclk)
   begin : po
   if (reset_oclk == 1'b 1)
      begin
      orst_reg3 <= 1'b 0;	
      orst_reg4 <= 1'b 0;	
      end
   else
      begin
      orst_reg3 <= orst_reg2;	
      orst_reg4 <= orst_reg3 & orst_reg2;       // assert delayed, deassert immediately
      end
   end

//  outputs
assign lsreset_out = lr_latch; 
assign osreset_out = orst_reg2; 

endmodule // module ff_sreset

